﻿using Microsoft.VisualStudio.TestTools.UnitTesting;

using DatabaseGroup.SSIS.SourceAdapters.Parser;

namespace DatabaseGroup.UnitTests.SSIS.SourceAdapters.Parser
{
    [TestClass()]
    public class MatchEscapedTokenParsingStateTest
    {
        private const string _expectedMissParsingResult =
            "Expected parsing result to be Miss based on not matching match token";
        private const string _expectedDoneParsingResult =
            "Expected parsing result to be Done based on completely matching whole match token with no further states";
        private const string _expectedMatchParsingResult =
            "Expected parsing result to be Match based on partially matching match token";
        private TestContext _testContextInstance;

        public TestContext TestContext
        {
            get
            {
                return _testContextInstance;
            }
            set
            {
                _testContextInstance = value;
            }
        }

        [TestMethod()]
        [ExpectedException(typeof(System.ArgumentNullException), "Expected ArgumentNullException to be thrown when called with empty arg")]
        public void MatchEscapedTokenParsingState_ConstructorWithEmptyArg_ThrowArgumentNullException()
        {
            MatchEscapedTokenParsingState target = new MatchEscapedTokenParsingState(string.Empty);
        }

        [TestMethod()]
        public void ProcessCharacter_SingleEscapedCharToken_ReturnExpectedParsingResult()
        {
            ParsingContextTestImpl context = new ParsingContextTestImpl();
            MatchEscapedTokenParsingState target = new MatchEscapedTokenParsingState("\"");
            Assert.AreEqual<ParsingResult>(ParsingResult.Miss, target.ProcessCharacter(context, 'a'), _expectedMissParsingResult);
            Assert.AreEqual<ParsingResult>(ParsingResult.Miss, target.ProcessCharacter(context, 'c'), _expectedMissParsingResult);
            Assert.AreEqual<ParsingResult>(ParsingResult.Match, target.ProcessCharacter(context, '\"'), _expectedMatchParsingResult);
            Assert.AreEqual<ParsingResult>(ParsingResult.Miss, target.ProcessCharacter(context, 'x'), _expectedMissParsingResult);
            Assert.AreEqual<ParsingResult>(ParsingResult.Match, target.ProcessCharacter(context, '\"'), _expectedMatchParsingResult);
            Assert.AreEqual<ParsingResult>(ParsingResult.Done, target.ProcessCharacter(context, '\"'), _expectedDoneParsingResult);
        }

        [TestMethod()]
        public void ProcessCharacter_MultiEscapedCharToken_ReturnExpectedParsingResult()
        {
            ParsingContextTestImpl context = new ParsingContextTestImpl();
            MatchEscapedTokenParsingState target = new MatchEscapedTokenParsingState(":\":");
            Assert.AreEqual<ParsingResult>(ParsingResult.Miss, target.ProcessCharacter(context, 'a'), _expectedMissParsingResult);
            Assert.AreEqual<ParsingResult>(ParsingResult.Miss, target.ProcessCharacter(context, 'c'), _expectedMissParsingResult);
            Assert.AreEqual<ParsingResult>(ParsingResult.Match, target.ProcessCharacter(context, ':'), _expectedMatchParsingResult);
            Assert.AreEqual<ParsingResult>(ParsingResult.Miss, target.ProcessCharacter(context, 'x'), _expectedMissParsingResult);
            Assert.AreEqual<ParsingResult>(ParsingResult.Match, target.ProcessCharacter(context, ':'), _expectedMatchParsingResult);
            Assert.AreEqual<ParsingResult>(ParsingResult.Match, target.ProcessCharacter(context, '\"'), _expectedMatchParsingResult);
            Assert.AreEqual<ParsingResult>(ParsingResult.Match, target.ProcessCharacter(context, ':'), _expectedMatchParsingResult);
            Assert.AreEqual<ParsingResult>(ParsingResult.Miss, target.ProcessCharacter(context, 'd'), _expectedMissParsingResult);
            Assert.AreEqual<ParsingResult>(ParsingResult.Match, target.ProcessCharacter(context, ':'), _expectedMatchParsingResult);
            Assert.AreEqual<ParsingResult>(ParsingResult.Match, target.ProcessCharacter(context, '\"'), _expectedMatchParsingResult);
            Assert.AreEqual<ParsingResult>(ParsingResult.Match, target.ProcessCharacter(context, ':'), _expectedMatchParsingResult);
            Assert.AreEqual<ParsingResult>(ParsingResult.Match, target.ProcessCharacter(context, ':'), _expectedMatchParsingResult);
            Assert.AreEqual<ParsingResult>(ParsingResult.Miss, target.ProcessCharacter(context, ','), _expectedMissParsingResult);
            Assert.AreEqual<ParsingResult>(ParsingResult.Match, target.ProcessCharacter(context, ':'), _expectedMatchParsingResult);
            Assert.AreEqual<ParsingResult>(ParsingResult.Match, target.ProcessCharacter(context, '\"'), _expectedMatchParsingResult);
            Assert.AreEqual<ParsingResult>(ParsingResult.Match, target.ProcessCharacter(context, ':'), _expectedMatchParsingResult);
            Assert.AreEqual<ParsingResult>(ParsingResult.Match, target.ProcessCharacter(context, ':'), _expectedMatchParsingResult);
            Assert.AreEqual<ParsingResult>(ParsingResult.Match, target.ProcessCharacter(context, '\"'), _expectedMatchParsingResult);
            Assert.AreEqual<ParsingResult>(ParsingResult.Done, target.ProcessCharacter(context, ':'), _expectedDoneParsingResult);
        }
    }
}
